package com.edu.chat.web.common.model;


import com.edu.chat.web.common.constants.CommonConstant;
import com.edu.chat.web.common.enums.ResultCodeEnum;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.util.ObjectUtils;

import javax.validation.constraints.NotNull;
import java.io.Serial;
import java.io.Serializable;
import java.util.Optional;

/**
 * @program: KQAIA
 * @description: 统一返回
 * @author: 无恙
 * @create: 2025-03-06 23:08
 **/
@Getter
@Setter
@ToString
@NoArgsConstructor
public class R<T> implements Serializable {

	@Serial
	private static final long serialVersionUID = 1L;

	private String code;
	private boolean success;
	@JsonInclude(JsonInclude.Include.NON_NULL)
	private T data;
	private String msg;

	private R(ResultCodeEnum ResultCodeEnum) {
		this(ResultCodeEnum.getCode(), null, ResultCodeEnum.getMsg());
	}

	private R(ResultCodeEnum ResultCodeEnum, String msg) {
		this(ResultCodeEnum, null, msg);
	}

	private R(ResultCodeEnum ResultCodeEnum, T data, String msg) {
		this(ResultCodeEnum.getCode(), data, msg);
	}

	private R(ResultCodeEnum ResultCodeEnum, T data) {
		this(ResultCodeEnum.getCode(), data, ResultCodeEnum.getMsg());
	}

	private R(String code, T data, String msg) {
		this.code = code;
		this.data = data;
		this.msg = msg;
		this.success = ResultCodeEnum.SUCCESS.getCode().equals(code);
	}


	/**
	 * 判断返回是否为成功
	 *
	 * @param result Result
	 * @return 是否成功
	 */
	public static boolean isSuccess(R<?> result) {
		return Optional.ofNullable(result)
				.map(x -> ObjectUtils.nullSafeEquals(ResultCodeEnum.SUCCESS.getCode(), x.code))
				.orElse(Boolean.FALSE);
	}

	/**
	 * 判断返回是否为成功
	 *
	 * @param result Result
	 * @return 是否成功
	 */
	public static boolean isNotSuccess(@NotNull R<?> result) {
		return !R.isSuccess(result);
	}

	/**
	 * 返回R
	 *
	 * @param data 数据
	 * @param <T>  T 泛型标记
	 * @return R
	 */
	public static <T> R<T> data(T data) {
		return data(data, CommonConstant.DEFAULT_SUCCESS_MESSAGE);
	}

	/**
	 * 返回R
	 *
	 * @param data 数据
	 * @param msg  消息
	 * @param <T>  T 泛型标记
	 * @return R
	 */
	public static <T> R<T> data(T data, String msg) {
		return data("200", data, msg);
	}

	/**
	 * 返回R
	 *
	 * @param code 状态码
	 * @param data 数据
	 * @param msg  消息
	 * @param <T>  T 泛型标记
	 * @return R
	 */
	public static <T> R<T> data(String code, T data, String msg) {
		return new R<>(code, data, data == null ? CommonConstant.DEFAULT_NULL_MESSAGE : msg);
	}

	/**
	 * 返回R
	 *
	 * @param msg 消息
	 * @param <T> T 泛型标记
	 * @return R
	 */
	public static <T> R<T> success(String msg) {
		return new R<>(ResultCodeEnum.SUCCESS, msg);
	}

	public static <T> R<T> success() {
		return new R<>(ResultCodeEnum.SUCCESS);
	}

	/**
	 * 返回R
	 *
	 * @param <T> T 泛型标记
	 * @return R
	 */
	public static <T> R<T> success(T data) {
		return new R<>(ResultCodeEnum.SUCCESS, data);
	}

	/**
	 * 返回R
	 *
	 * @param ResultCodeEnum 业务代码
	 * @param <T>            T 泛型标记
	 * @return R
	 */
	public static <T> R<T> success(ResultCodeEnum ResultCodeEnum) {
		return new R<>(ResultCodeEnum);
	}

	/**
	 * 返回R
	 *
	 * @param ResultCodeEnum 业务代码
	 * @param msg            消息
	 * @param <T>            T 泛型标记
	 * @return R
	 */
	public static <T> R<T> success(ResultCodeEnum ResultCodeEnum, String msg) {
		return new R<>(ResultCodeEnum, msg);
	}

	/**
	 * 返回R
	 *
	 * @param msg 消息
	 * @param <T> T 泛型标记
	 * @return R
	 */
	public static <T> R<T> fail(String msg) {
		return new R<>(ResultCodeEnum.FAIL, msg);
	}

	/**
	 * 返回R
	 *
	 * @param msg 消息
	 * @param <T> T 泛型标记
	 * @return R
	 */
	public static <T> R<T> fail(String msg, T data) {
		return new R<>(ResultCodeEnum.FAIL.getCode(), data, msg);
	}


	/**
	 * 返回R
	 *
	 * @param code 状态码
	 * @param msg  消息
	 * @param <T>  T 泛型标记
	 * @return R
	 */
	public static <T> R<T> fail(String code, String msg) {
		return new R<>(code, null, msg);
	}

	/**
	 * 返回R
	 *
	 * @param code 状态码
	 * @param msg  消息
	 * @param <T>  T 泛型标记
	 * @return R
	 */
	public static <T> R<T> fail(String code, String msg, T data) {
		return new R<>(code, data, msg);
	}

	/**
	 * 返回R
	 *
	 * @param ResultCodeEnum 业务代码
	 * @param <T>            T 泛型标记
	 * @return R
	 */
	public static <T> R<T> fail(ResultCodeEnum ResultCodeEnum) {
		return new R<>(ResultCodeEnum);
	}

	/**
	 * 返回R
	 *
	 * @param ResultCodeEnum 业务代码
	 * @param <T>            T 泛型标记
	 * @return R
	 */
	public static <T> R<T> fail(ResultCodeEnum ResultCodeEnum, T data) {
		return new R<>(ResultCodeEnum, data);
	}

	/**
	 * 返回R
	 *
	 * @param ResultCodeEnum 业务代码
	 * @param msg            消息
	 * @param <T>            T 泛型标记
	 * @return R
	 */
	public static <T> R<T> fail(ResultCodeEnum ResultCodeEnum, String msg) {
		return new R<>(ResultCodeEnum, msg);
	}

	/**
	 * 返回R
	 *
	 * @param flag 成功状态
	 * @return R
	 */
	public static <T> R<T> status(boolean flag) {
		return flag ? success(CommonConstant.DEFAULT_SUCCESS_MESSAGE) : fail(CommonConstant.DEFAULT_FAILURE_MESSAGE);
	}
}